package com.dctp.common.manager;

import com.dctp.common.cache.DictionaryCache;
import com.dctp.common.core.RedisManager;
import com.dctp.common.db.DictionaryDb;
import com.dctp.common.utils.StringUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.DayOfWeek;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;

public class ProjectManager {

    private static final String REDIS_KEY_PREFIX_DYN = "risk:dyn:";
    private static final String REDIS_KEY_PREFIX_DAYLOSS = "risk:dayloss:";
    private static final int CACHE_EXPIRE = 300; // 缓存5分钟

    // ✅ 用 Caffeine 替代 HashMap
    private static final Cache<Long, Record> dynRiskCache = Caffeine.newBuilder()
            .expireAfterWrite(CACHE_EXPIRE, TimeUnit.SECONDS)
            .maximumSize(50_000)   // 看你用户量，5万条足够了
            .build();

    private static final Cache<Long, Record> dayLossRiskCache = Caffeine.newBuilder()
            .expireAfterWrite(CACHE_EXPIRE, TimeUnit.SECONDS)
            .maximumSize(50_000)
            .build();

//    private static LocalTime[] dateTimes;


    private static LocalTime startTime;
    private static LocalTime endTime;

    public static LocalDateTime[] getDayTime() {


        if (null == startTime) {
            String profitStatBeginTime = DictionaryDb.getValueByCode("profitStatBeginTime");
            if (StringUtil.isEmpty(profitStatBeginTime)) {
                profitStatBeginTime = "08:00:00";
            }
            startTime = LocalTime.parse(profitStatBeginTime);
        }


        if (null == endTime) {
            String profitStatEndTime = DictionaryDb.getValueByCode("profitStatEndTime");
            if (StringUtil.isEmpty(profitStatEndTime)) {
                profitStatEndTime = "08:00:00";
            }
            endTime =  LocalTime.parse(profitStatEndTime);
        }

        LocalDate nowDate = LocalDate.now();
        LocalTime nowTime = LocalTime.now();
        LocalDateTime beginDateTime;
        LocalDateTime endDateTime;

        if (nowTime.isBefore(startTime)) {
            beginDateTime = nowDate.minusDays(1).atTime(startTime);
            endDateTime = nowDate.atTime(endTime);
        } else {
            beginDateTime = nowDate.atTime(startTime);
            endDateTime = nowDate.plusDays(1).atTime(endTime);
        }
        return new LocalDateTime[]{beginDateTime, endDateTime};
    }

    /**
     * ✅ 获取动态风控参数（Caffeine + Redis + DB）
     */
    public static Record getDynRiskParams(Long userId) {

        return dynRiskCache.get(userId, id -> {

            RedisManager redis = RedisManager.getInstance();

            // 1️⃣ 系统默认配置
            Record riskParams = DictionaryCache.getDictValues(
                    "dyn_warning_line", "dyn_forbid_open_line", "dyn_force_close_line"
            );

            // 2️⃣ 查 Redis（用户配置）
            String redisKey = REDIS_KEY_PREFIX_DYN + userId;
            Map<String, String> redisData = redis.hgetAll(redisKey);

            if (redisData == null || redisData.isEmpty()) {
                // 3️⃣ Redis 没有 → 查数据库
                Record dbRecord = Db.findFirst(
                        "SELECT dyn_warning_line, dyn_forbid_open_line, dyn_force_close_line " +
                                "FROM dctp_risk_metric WHERE user_id = ? AND dyn_enabled = 1",
                        userId
                );

                if (dbRecord != null) {
                    riskParams.setColumns(dbRecord);
                    // ✅ 写回 Redis
                    redis.pipeline(p -> {
                        for (Map.Entry<String, Object> entry : dbRecord.getColumns().entrySet()) {
                            if (entry.getValue() != null) {
                                p.hset(redisKey, entry.getKey(), entry.getValue().toString());
                            }
                        }
                        p.expire(redisKey, CACHE_EXPIRE);
                    });
                }
            } else {
                // ✅ Redis 命中，覆盖默认值
                for (Map.Entry<String, String> e : redisData.entrySet()) {
                    riskParams.set(e.getKey(), e.getValue());
                }
            }
            return riskParams;
        });
    }

    /**
     * ✅ 获取日亏损风控参数（Caffeine + Redis + DB）
     */
    public static Record getDayLossRiskParams(Long userId) {
        return dayLossRiskCache.get(userId, id -> {
            RedisManager redis = RedisManager.getInstance();

            // 1️⃣ 系统默认配置
            Record riskParams = DictionaryCache.getDictValues(
                    "daily_loss_warning_line", "daily_loss_forbid_open", "daily_loss_force_close"
            );

            // 2️⃣ 查 Redis（用户配置）
            String redisKey = REDIS_KEY_PREFIX_DAYLOSS + userId;
            Map<String, String> redisData = redis.hgetAll(redisKey);

            if (redisData == null || redisData.isEmpty()) {
                // 3️⃣ Redis 没有 → 查数据库
                Record dbRecord = Db.findFirst(
                        "SELECT daily_loss_warning_line, daily_loss_forbid_open, daily_loss_force_close " +
                                "FROM dctp_risk_metric WHERE user_id = ? AND daily_loss_enabled = 1",
                        userId
                );

                if (dbRecord != null) {
                    riskParams.setColumns(dbRecord);
                    // ✅ 写回 Redis
                    redis.pipeline(p -> {
                        for (Map.Entry<String, Object> entry : dbRecord.getColumns().entrySet()) {
                            if (entry.getValue() != null) {
                                p.hset(redisKey, entry.getKey(), entry.getValue().toString());
                            }
                        }
                        p.expire(redisKey, CACHE_EXPIRE);
                    });
                }
            } else {
                // ✅ Redis 命中，覆盖默认值
                for (Map.Entry<String, String> e : redisData.entrySet()) {
                    riskParams.set(e.getKey(), e.getValue());
                }
            }

            return riskParams;
        });
    }

    public static boolean isBTCTradeForbiddenNow() {
        LocalTime now = LocalTime.now();
        DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
        if (dayOfWeek != DayOfWeek.FRIDAY) {
            return false;
        }
        String btcUnTradeTime = DictionaryDb.getValueByCode("btcUnTradeTime");
        if (StringUtil.isEmpty(btcUnTradeTime)) {
            return false;
        }
        String [] arrs = btcUnTradeTime.split("#");
        if (arrs.length != 3) {
            return false;
        }
        LocalTime start = LocalTime.parse(arrs[1]);
        LocalTime end = LocalTime.parse(arrs[2]);
        return !now.isBefore(start) && !now.isAfter(end);
    }
}
